#define _GNU_SOURCE
#include "daemon_runner.h"
#include "daemon_sub_process.h"
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>

static int is_running = 1; // 是否运行的标识

static SubProcess *sub_processes[SUB_PROCESS_COUNT];
static char *params[] = {"app", "ota"};  // 所有子进程程序的参数


// 信号处理函数: 守护进程被kill了
void signal_handler(int signo)
{
    is_running = 0;
}

/**
 * 运行函数
 * 1. 将当前进程变成守护进程
 * 2. 将标准输出重定向到日志文件
 * 3. 注册进程结束的信号监听 =》 用于在守护结束前关闭所有子进程
 * 4. 初始化所有子进程信息
 * 5. 每隔2秒检查启动所有子进程
 * 6. 关闭所有子进程
 */
int daemon_runner_run()
{
    // 将当前进程变成守护进程
        // 参数1： 0  指定当选程序的工作目录不再是所在的目录，而是根目录 =》防止不能卸载当前程序
        // 参数2： 1  不关闭标准输入、标准输出、标准错误  0：关闭
    daemon(0, 1);
    // 关闭标准输入，重定向到/dev/null  =》 不能再接收标准输入
    // 关闭标准输出/标准错误输出，重定向到日志文件
    close(STDERR_FILENO); // 2
    close(STDOUT_FILENO); // 1
    close(STDIN_FILENO); // 0
    open("/dev/null", O_RDWR); // 0 => 标准输入
    open(LOG_FILE, O_CREAT|O_WRONLY|O_APPEND, 0644); // 1  => 标准输出
    open(LOG_FILE, O_CREAT|O_WRONLY|O_APPEND, 0644); // 2  => 标准错误输出
    // 注册进程结束的信号监听 =》 用于在守护结束前关闭所有子进程
    signal(SIGTERM, signal_handler);

    // 初始要启动的所有子进程信息（结构体）
    for (int i = 0; i < SUB_PROCESS_COUNT; i++)
    {
        sub_processes[i] = daemon_sub_process_init(params[i]);
    }
    
    // 循环启动子进程
    while (is_running)
    {
        for (int i = 0; i < SUB_PROCESS_COUNT; i++)
        {
            daemon_sub_process_checkStart(sub_processes[i]);
        }
        // 休眠2秒之后进行检查启动
        sleep(2);
    }

    // 关闭所有子进程
    for (int i = 0; i < SUB_PROCESS_COUNT; i++)
    {
        daemon_sub_process_close(sub_processes[i]);
    }

}